import NProgress from 'nprogress'
import { dynamicRouter } from '@/utils'
import { StorageEnum } from '@/common/enums'
import { ElMessage } from 'element-plus'
import { queryRoutes } from '@/api/menu'
import { useAsideStore } from '@store/aside'
import type { Router, NavigationGuardWithThis } from 'vue-router'

type beforeEachDynamicType = (
  router: Router,
) => NavigationGuardWithThis<undefined>

// 路由白名单
const whiteList = ['/login', '/register']

// 获取动态路由
export const beforeEachDynamic: beforeEachDynamicType = (router) => {
  return async (to, _from, next) => {
    NProgress.start()
    // 存在白名单
    const _path = to.path
    if (whiteList.includes(_path)) {
      NProgress.done()
      return next()
    }

    // 如果路由表中存在该路由，直接放行
    if (router.hasRoute(to.name as string)) {
      NProgress.done()
      return next()
    }

    // 查看用户是否登录
    const userId = localStorage.getItem(StorageEnum.USER_ID)
    if (!userId) {
      NProgress.done()
      return next('/login')
    }
    // 查看是否存在路由表
    let menus = localStorage.getItem(StorageEnum.MENU)
    if (!menus) {
      const asideStore = useAsideStore()
      // 获取用户权限
      const userInfo = JSON.parse(
        localStorage.getItem(StorageEnum.USER_INFO) as string,
      )
      const menusResp = await queryRoutes({
        permission: userInfo.permission,
      })
      if (menusResp.length === 0) {
        NProgress.done()
        ElMessage.error('暂无权限查看，请联系管理员！')
        return next('/login')
      }
      // 将数据转为路由，动态添加到路由中
      const routeResp = await dynamicRouter(menusResp)
      // 动态添加路由
      // @see: https://router.vuejs.org/zh/guide/advanced/dynamic-routing.html
      routeResp.forEach((item) => {
        router.addRoute('layout', item)
      })
      NProgress.done()
      // 更新侧边栏
      asideStore.updateAsideList(menusResp)
      next({ path: to.fullPath })
    } else {
      menus = JSON.parse(menus)
      const routeResp = await dynamicRouter(menus as unknown as any[])
      routeResp.forEach((item) => {
        router.addRoute('layout', item)
      })
      next({ path: to.fullPath })
    }
  }
}
